#ifndef _PIPELINE_H_
#define _PIPELINE_H_


#include <sys/types.h>


/** <DEFS> **/

/** <SETTINGS> **/
#define _PIPELINE_DEBUG     (0)
#define MAX_STAGES          (8)
#define MAX_PROCS_PER_STAGE (16)
#define MAX_PIPES_PER_STAGE (MAX_PROCS_PER_STAGE)
/** </SETTINGS> **/

#define IN_RANGE(x, a, b) ((x >= a) && (x <= b))
#define PIPE_CLOSED (-1)


/** <TYPES> **/

/* Directions for n-th stage's forward pipes */
typedef enum fw_pipes_dirs_t {
  PIPES_MONO, /* [read/write] <--> (stage) ---> [write]       */
  PIPES_BI    /* [read/write] <--> (stage) <--> [read/write]  */
} fw_pipes_dirs_t;

/* Mode for n-th stage's forward pipes */
typedef enum fw_pipes_shr_t {
  PIPES_SHA,  /* forward pipes are shared between tasks for this stage */
  PIPES_PVT   /* each task for this stage has a private forward pipe */
} fw_pipes_shr_t;

/* The interface between two stages */
typedef struct iface_t {
  int r_pipes[MAX_PIPES_PER_STAGE]; /* reading ends */
  int w_pipes[MAX_PIPES_PER_STAGE]; /* writing ends */
  unsigned int count;               /* r_pipes[] (and w_pipes[]) count */
} iface_t;

/* A pointer to a stage task */
typedef void (*stage_task_ptr)(
        unsigned int, /* task id */
        iface_t*,     /* backward pipes */
        iface_t*      /* forward pipes */
  );

/* A stage specification */
typedef struct stage_spec_t {
  unsigned int    n_procs;
  unsigned int    n_pipes;
  fw_pipes_dirs_t fwp_dirs;
  fw_pipes_shr_t  fwp_shr;
  stage_task_ptr  task;
} stage_spec_t;

/** </TYPES> **/


/** <PROTO> **/

/* Build up the pipeline with given parameters. */
void pipeline(  iface_t*       main_bw_if,
                stage_spec_t   stage_specs[],
                unsigned int   n_stages  );

/** </PROTO> **/

/** </DEFS> **/

#endif /* _PIPELINE_H_ */
